package cuongnh.project.japanesediary.vocabulary.ui.editor.vocabulary.page.grammar.section;

import java.util.Set;

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.ObservableSetContentProvider;
import org.eclipse.jface.databinding.viewers.ViewerProperties;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.forms.SectionPart;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.wb.swt.SWTResourceManager;

import cuongnh.project.japanesediary.vocabulary.application.Activator;
import cuongnh.project.japanesediary.vocabulary.common.CommonServices;
import cuongnh.project.japanesediary.vocabulary.common.CommonUtils;
import cuongnh.project.japanesediary.vocabulary.model.Grammar;
import cuongnh.project.japanesediary.vocabulary.model.Vocabulary;
import cuongnh.project.japanesediary.vocabulary.ui.dialog.AddRelatedGrammarDialog;

public class VocabularyGrammarsSection extends SectionPart {

	private DataBindingContext m_bindingContext;
	private Vocabulary vocabulary;
	private CommonServices commonServices;
	private Text txtGrammar;
	private Text txtVnUsage;
	private TableViewer tblRelatedGrammarList;
	private boolean dirtyEditor = false;

	/**
	 * @wbp.parser.constructor
	 */
	public VocabularyGrammarsSection(Composite parent, FormToolkit toolkit,
			int style) {
		super(parent, toolkit, style);
		createClient(getSection(), toolkit);
	}

	/**
	 * Create the SectionPart.
	 * 
	 * @param parent
	 * @param toolkit
	 * @param style
	 */
	public VocabularyGrammarsSection(Composite parent, FormToolkit toolkit,
			int style, Vocabulary vocabulary, CommonServices commonServices) {
		super(parent, toolkit, style);
		this.commonServices = commonServices;
		this.vocabulary = vocabulary;
		initData();
		createClient(getSection(), toolkit);
	}

	public void initData() {
		vocabulary = commonServices.getVocabularyDao()
				.getVocabularyWithGrammars(vocabulary.getVocabularyId());
	}

	/**
	 * Fill the section.
	 */
	private void createClient(Section section, FormToolkit toolkit) {
		section.setText("Related Grammars");
		createToolBar(section);
		Composite container = toolkit.createComposite(section);

		section.setClient(container);
		container.setLayout(new GridLayout(1, false));

		Composite meaningComposite = new Composite(container, SWT.NONE);
		meaningComposite.setBackground(SWTResourceManager
				.getColor(SWT.COLOR_WHITE));
		meaningComposite.setLayout(new GridLayout(2, false));
		meaningComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
				true, 1, 1));

		Composite compGrammars = new Composite(meaningComposite, SWT.NONE);
		GridData gd_compGrammars = new GridData(SWT.FILL, SWT.FILL, false,
				false, 1, 1);
		gd_compGrammars.heightHint = 223;
		gd_compGrammars.widthHint = 456;
		compGrammars.setLayoutData(gd_compGrammars);
		tblRelatedGrammarList = new TableViewer(compGrammars, SWT.BORDER
				| SWT.FULL_SELECTION);
		Table table = tblRelatedGrammarList.getTable();
		table.setLinesVisible(true);
		table.setHeaderVisible(true);
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		TableViewerColumn tbclvGrammar = new TableViewerColumn(
				tblRelatedGrammarList, SWT.NONE);
		TableColumn tblclmnGrammar = tbclvGrammar.getColumn();
		tblclmnGrammar.setWidth(100);
		tblclmnGrammar.setText("Grammar");
		TableViewerColumn tbclvVnMeaning = new TableViewerColumn(
				tblRelatedGrammarList, SWT.NONE);
		TableColumn tblclmnVnMeaning = tbclvVnMeaning.getColumn();
		tblclmnVnMeaning.setWidth(100);
		tblclmnVnMeaning.setText("Vietnamese meaning");
		TableColumnLayout tblColumnLayout = new TableColumnLayout();
		tblColumnLayout.setColumnData(tblclmnGrammar, new ColumnWeightData(35,
				true));
		tblColumnLayout.setColumnData(tblclmnVnMeaning, new ColumnWeightData(
				60, true));
		compGrammars.setLayout(tblColumnLayout);

		Composite composite = new Composite(meaningComposite, SWT.NONE);
		composite.setLayout(new GridLayout(1, false));
		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1,
				1));

		Label lblGrammar = new Label(composite, SWT.NONE);
		lblGrammar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
				false, 1, 1));
		lblGrammar.setAlignment(SWT.CENTER);
		lblGrammar
				.setFont(SWTResourceManager.getFont("Segoe UI", 10, SWT.BOLD));
		lblGrammar.setForeground(SWTResourceManager
				.getColor(SWT.COLOR_DARK_RED));
		lblGrammar.setBackground(SWTResourceManager
				.getColor(SWT.COLOR_TITLE_BACKGROUND));
		lblGrammar.setText("Grammar");

		txtGrammar = new Text(composite, SWT.BORDER | SWT.WRAP | SWT.CENTER
				| SWT.MULTI);
		txtGrammar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false,
				1, 1));
		txtGrammar.setForeground(SWTResourceManager.getColor(SWT.COLOR_RED));
		txtGrammar
				.setFont(SWTResourceManager.getFont("Segoe UI", 20, SWT.BOLD));
		txtGrammar.setEditable(false);

		Label lblVietnameseExplaination = new Label(composite, SWT.NONE);
		lblVietnameseExplaination.setAlignment(SWT.CENTER);
		lblVietnameseExplaination.setLayoutData(new GridData(SWT.FILL,
				SWT.FILL, true, false, 1, 1));
		lblVietnameseExplaination.setFont(SWTResourceManager.getFont(
				"Segoe UI", 10, SWT.BOLD));
		lblVietnameseExplaination.setForeground(SWTResourceManager
				.getColor(SWT.COLOR_DARK_RED));
		lblVietnameseExplaination.setBackground(SWTResourceManager
				.getColor(SWT.COLOR_TITLE_BACKGROUND));
		lblVietnameseExplaination.setText("Vietnamese explaination");

		txtVnUsage = new Text(composite, SWT.BORDER | SWT.WRAP | SWT.MULTI);
		txtVnUsage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true,
				1, 1));
		txtVnUsage.setEditable(false);

		tblRelatedGrammarList.getTable().addListener(SWT.Selection,
				new Listener() {

					@Override
					public void handleEvent(Event event) {
						if (dirtyEditor == false && isDirty() == true) {
							commit(false);
							getManagedForm().dirtyStateChanged();
						}
					}

				});

		tblRelatedGrammarList
				.addSelectionChangedListener(new ISelectionChangedListener() {

					@Override
					public void selectionChanged(SelectionChangedEvent event) {
						dirtyEditor = isDirty();
					}
				});

		CommonUtils.grammarsHookDoubleClickCommand(tblRelatedGrammarList);

		m_bindingContext = initDataBindings();
		IChangeListener listener = new IChangeListener() {
			@Override
			public void handleChange(ChangeEvent event) {
				markDirty();
			}
		};

		IObservableList bindings = m_bindingContext.getBindings();

		// Register the listener to all bindings
		for (Object o : bindings) {
			Binding b = (Binding) o;
			b.getModel().addChangeListener(listener);
		}
	}

	private void createToolBar(Section section) {
		ToolBar toolbar = new ToolBar(section, SWT.FLAT);
		section.setTextClient(toolbar);

		ToolItem addItem = new ToolItem(toolbar, SWT.PUSH);
		addItem.setImage(Activator.getImageDescriptor("/icons/add.gif")
				.createImage());
		addItem.setToolTipText("Add a new related grammar for this vocabulary");

		addItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				AddRelatedGrammarDialog relatedGrammarDialog = new AddRelatedGrammarDialog(
						getSection().getShell(), commonServices);
				if (relatedGrammarDialog.open() == Window.OK) {
					Set<Grammar> selectedGrammars = relatedGrammarDialog
							.getSelectedGrammars();
					vocabulary.getGrammars().addAll(selectedGrammars);
					// commonServices.getVocabularyDao().update(vocabulary);
					m_bindingContext.updateModels();
					tblRelatedGrammarList.refresh();
					tblRelatedGrammarList.setSelection(new StructuredSelection(selectedGrammars.toArray()));
				}
			}
		});

		ToolItem removeItem = new ToolItem(toolbar, SWT.PUSH);
		removeItem.setImage(Activator.getImageDescriptor("/icons/delete.gif")
				.createImage());
		removeItem
				.setToolTipText("Remove selected related grammar for this vocabulary");

		removeItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection selection = (IStructuredSelection) tblRelatedGrammarList
						.getSelection();
				Set<Grammar> selectedGrammars = CommonUtils
						.getSelectedGrammars(selection);
				boolean confirm = MessageDialog
						.openConfirm(getSection().getShell(), "Confirm Delete",
								"Are you sure you want to delete this related grammar?");
				if (confirm) {
					vocabulary.getGrammars().removeAll(selectedGrammars);
					m_bindingContext.updateModels();
					tblRelatedGrammarList.refresh();
					makeGrammarEditable(false);
				}
			}
		});

		ToolItem editItem = new ToolItem(toolbar, SWT.PUSH);
		editItem.setImage(Activator.getImageDescriptor("/icons/pencil.png")
				.createImage());
		editItem.setToolTipText("Edit selected grammar");

		editItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				makeGrammarEditable(true);
			}
		});
	}

	@Override
	public void commit(boolean onSave) {
		super.commit(onSave);
		commonServices.getVocabularyDao().merge(vocabulary);
		tblRelatedGrammarList.refresh();
	}

	private void makeGrammarEditable(boolean editable) {
		txtGrammar.setEditable(editable);
		txtVnUsage.setEditable(editable);
	}

	protected DataBindingContext initDataBindings() {
		DataBindingContext bindingContext = new DataBindingContext();
		//
		ObservableSetContentProvider setContentProvider = new ObservableSetContentProvider();
		IObservableMap[] observeMaps = BeansObservables.observeMaps(
				setContentProvider.getKnownElements(), Grammar.class,
				new String[] { "grammar", "vnMeaning" });
		tblRelatedGrammarList.setLabelProvider(new ObservableMapLabelProvider(
				observeMaps));
		tblRelatedGrammarList.setContentProvider(setContentProvider);
		//
		IObservableSet grammarsVocabularyObserveSet = BeanProperties.set(
				"grammars").observe(vocabulary);
		tblRelatedGrammarList.setInput(grammarsVocabularyObserveSet);
		//
		IObservableValue observeSingleSelectionTblRelatedGrammarList = ViewerProperties
				.singleSelection().observe(tblRelatedGrammarList);
		IObservableValue tblRelatedGrammarListGrammarObserveDetailValue = BeanProperties
				.value(Grammar.class, "grammar", String.class).observeDetail(
						observeSingleSelectionTblRelatedGrammarList);
		IObservableValue observeTextTxtGrammarObserveWidget = WidgetProperties
				.text(SWT.Modify).observe(txtGrammar);
		bindingContext.bindValue(
				tblRelatedGrammarListGrammarObserveDetailValue,
				observeTextTxtGrammarObserveWidget, null, null);
		//
		IObservableValue observeSingleSelectionTblRelatedGrammarList_1 = ViewerProperties
				.singleSelection().observe(tblRelatedGrammarList);
		IObservableValue tblRelatedGrammarListVnUsageObserveDetailValue = BeanProperties
				.value(Grammar.class, "vnUsage", String.class).observeDetail(
						observeSingleSelectionTblRelatedGrammarList_1);
		IObservableValue observeTextTxtVnUsageObserveWidget = WidgetProperties
				.text(SWT.Modify).observe(txtVnUsage);
		bindingContext.bindValue(
				tblRelatedGrammarListVnUsageObserveDetailValue,
				observeTextTxtVnUsageObserveWidget, null, null);
		//
		return bindingContext;
	}
}
